package com.dc.gameserver.extComponents.Scence;

import javolution.util.FastTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Vector;

/**
 * @author :陈磊 <br/>
 *         Project:CreazyGameServer1.5
 *         Date: 13-3-23
 *         Time: 上午11:15
 *         connectMethod:13638363871@163.com<br/>
 *         地图单元结构对象
 */
public class MapArea {

    private static final Logger LOG = LoggerFactory.getLogger(MapArea.class);
    private final int mapId;  //地图ID
    private final int wide;   //地图的宽
    private final int height; //地图的长
    private MapUnit mapUnits[] = null;  //存储地图单元
    private final int cellLength;// 单元格边长
    private final int rows;  //(行)
    private final int cols;  //(列)
    // 有MapStatus状态变量
    private  static final  ThreadLocal<MapStatus> threadLocal=new ThreadLocal<MapStatus>();

    /**
     * 设定对象在地图上的状态 变量
     * @param mapStatus         MapStatus
     */
    public void setMapStatus(MapStatus mapStatus){
        threadLocal.set(mapStatus);
    }

    /**
     * 获取对象在地图上的状态 变量
     * @return   MapStatus
     */
    public MapStatus getCurrentMapStatus() {
        return  threadLocal.get();
    }

    /**
     * 对象在地图上的状态 变量
     * 清除当前线程中的值，显示的调用，加快内存的回收
     */
    public void remove(){
        threadLocal.remove();
    }


    /**
     * 地图实例化
     * @param mapId   地图ID
     * @param wide    地图的宽
     * @param height  地图的高
     * @param cellLength 单元格边长
     */
    public MapArea(int mapId,int wide,int height,int cellLength){
        this.mapId = mapId;
        this.wide = wide;
        this.height = height;
        this.cellLength = cellLength;

        if (wide % cellLength > 0) {
            cols = (wide / cellLength) + 1;
        } else {
            cols = wide/ cellLength;
        }
        if (height % cellLength > 0) {
            rows = (height/ cellLength) + 1;
        } else {
            rows = height/ cellLength;
        }
        this.mapUnits=new MapUnit[rows*cols];

        //初始化每一个地图单元
        for (int row = 0; row < rows; row++){
            for (int col = 0; col < cols; col++) {
                this.mapUnits[row * cols + col] = new MapUnit(row * cols + col);
            }
        }

        //注册地图之间的关系
        for (int row = 0; row < rows; row++){
            for (int col = 0; col < cols; col++){
                MapUnit unit = this.mapUnits[row * cols + col];
                for (int x = -1; x < 2; x++) {
                    for (int y = -1; y < 2; y++) {
                        if ((((row + x) >= 0) &&
                                ((row + x) < rows)&& ((col + y) >= 0) && ((col + y) < cols)))// 现在时包含了自己单元格的
                        {
                            unit.addObserver(this.mapUnits[(row + x) * cols + col + y]);
                        }
                    }
                }
            }
        }
        //计算地图单元,相邻单元的消失单元和新增单元。
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                MapUnit unit = this.mapUnits[row * cols + col];// 得到地图上的每一个Unit
                // 开始遍历这个unit 可能重叠的 区域（unit）
                for (int i = -2; i <= 2; i++) {
                    for (int j = -2; j <= 2; j++) {
                        if ((((row + i) >= 0) && ((row + i) < rows)&& ((col + j) >= 0) && ((col + j) < cols))) {
                            FastTable<MapUnit> list = new FastTable<MapUnit>();
                            FastTable<MapUnit> ListOld = new FastTable<MapUnit>();
                            FastTable<MapUnit> ListNew = new FastTable<MapUnit>();
                            MapUnit TfiveJiu = this.mapUnits[(row + i) * cols+ (col + j)];
                            for (MapUnit oldnear : unit.getNearUnit())// 九个单元格
                            {
                                int stat = 0;
                                for (MapUnit newnear : TfiveJiu.getNearUnit())// 二十五个中的九个
                                {
                                    if (oldnear.getID() == newnear.getID())// 这里有且只有一个
                                    {
                                        list.add(this.mapUnits[oldnear.getID()]);
                                        stat = 1;
                                    }
                                }
                                if (stat != 1) {
                                    ListOld.add(this.mapUnits[oldnear.getID()]);
                                }
                                unit.getJiaoMap().put(TfiveJiu.getID(), list);
                                unit.getOldMap().put(TfiveJiu.getID(), ListOld);
                            }

                            //获取新增区域
                            for (MapUnit newnear : TfiveJiu.getNearUnit())// 二十五个中的每一个九个
                            {
                                int stat = 0;
                                for (MapUnit oldnear : unit.getNearUnit())// 九个单元格
                                {
                                    if (oldnear.getID() == newnear.getID()){
                                        stat = 1;
                                    }
                                }
                                if (stat != 1) {
                                    ListNew.add(this.mapUnits[newnear.getID()]);
                                }
                                unit.getNewMap().put(TfiveJiu.getID(), ListNew);
                            }
                        }
                    }
                }
            }
        }
    }


    /**
     * 根据坐标计算玩家所在的单元格--
     * @param x
     * @param y
     * @return int 单元格编号
     */
    public int getMapUnitID(int x,int y){
        return x/cellLength + (y / cellLength)*cols;
    }


    /**根据坐标计算玩家所在的单元格 编号
     * @param x
     * @param z
     * @return 3D    单元格编号
     */
    public int _getMapUnitID(int x,int z){
        return (x + wide/2) / cellLength + ((-z + height/2) / cellLength)*cols;
    }

    /**
     * 地图单元格对象
     * @return  MapUnit
     */
    public MapUnit[] getMapUnits() {
        return mapUnits;
    }


    public void setMapUnits(MapUnit[] mapUnits) {
        this.mapUnits = mapUnits;
    }

    /**
     * 地图编号
     * @return
     */
    public int getMapId() {
        return mapId;
    }

    /**
     *  地图的宽
     * @return wide
     */
    public int getWide() {
        return wide;
    }
    /**
     *  地图的高
     * @return height
     */
    public int getHeight() {
        return height;
    }

    /**
     * 单元格长度
     * @return cellLength
     */
    public int getCellLength() {
        return cellLength;
    }
    /**
     * 行
     * @return rows
     */
    public int getRows() {
        return rows;
    }
    /**
     * 列
     * @return cols
     */
    public int getCols() {
        return cols;
    }


    /**
     *  获取消失区域的ID列表（消失的单元格对象）
     *
     * @param curAreaId 当前的区域--单元格ID
     * @param oldAreaId 之前的区域 --单元格ID
     * @return  List<Integer>
     */
    public List<Integer> getOldAreaId(int curAreaId,int oldAreaId){
        List<Integer> list = new FastTable<Integer>();

        MapUnit curUnit = mapUnits[curAreaId];//当前的地图单元格
        Vector Curobs = curUnit.getObs(); //当前区域观察者列表

        MapUnit oldUnit = mapUnits[oldAreaId];
        Vector oldobs = oldUnit.getObs(); //老观察者列表



        List<MapUnit> listTemp = new FastTable<MapUnit>();  //相同的

        for(Object old:oldobs){
            MapUnit temp1 = (MapUnit)old;
            for(Object object:Curobs){
                MapUnit temp2 = (MapUnit)object;
                if(temp1.getID() == temp2.getID()){
                    listTemp.add(temp1);
                }
            }
        }

        //找出消失的区域
        for(Object old:oldobs){
            int status = 0;
            for(MapUnit mapUnit:listTemp){
                if(((MapUnit)old).getID() ==mapUnit.getID()){
                    status = 1;
                    break;
                }
            }
            if(status==0){
                list.add(((MapUnit)old).getID());
            }
        }

        return list;

    }

    /**
     *  获取新出现区域的ID列表--新增单元格对象
     * @param curAreaId  当前的区域--单元格ID
     * @param oldAreaId   之前的区域 --单元格ID
     * @return List<Integer>
     */
    public List<Integer> getNewAreaId(int curAreaId,int oldAreaId){
        List<Integer> list = new FastTable<Integer>();

        MapUnit curUnit = mapUnits[curAreaId];
        Vector Curobs = curUnit.getObs(); //当前区域观察者列表

        MapUnit oldUnit = mapUnits[oldAreaId];
        Vector oldobs = oldUnit.getObs(); //老观察者列表

        //对比观察者，找出消失的

        List<MapUnit> listTemp = new FastTable<MapUnit>();  //相同的


        for(Object old:oldobs){
            MapUnit temp1 = (MapUnit)old;
            for(Object gurob:Curobs){
                MapUnit temp2 = (MapUnit)gurob;
                if(temp1.getID() == temp2.getID()){
                    listTemp.add(temp1);
                }
            }
        }
        for(Object objUnit:Curobs){
            int status = 0;
            for (MapUnit mapUnit:listTemp){
                if(((MapUnit)objUnit).getID() ==mapUnit.getID()){
                    status = 1;
                    break;
                }
            }
            if(status==0){
                list.add(((MapUnit)objUnit).getID());
            }
        }
        return list;

    }


    /**
     *  获取当前区域的指定ID列表 ---指定（ID）单元格对象
     * @param AreaId ---单元格对象ID
     * @return  List<Integer>
     */
    public List<Integer> getCurAreaID(int AreaId){
        List<Integer> list = new FastTable<Integer>();

        MapUnit curUnit = mapUnits[AreaId];
        Vector Curobs = curUnit.getObs(); //当前区域观察者列表

        for(Object mapUnit:Curobs){
            list.add(((MapUnit)mapUnit).getID());
        }
        return list;
    }

    /**
     *  核实obj对象的位置
     * @param GameObj  游戏对象
     * @param nowMapUnit  当前单元格对象（ID）
     */
    public void checkLocation(WordObject GameObj,int nowMapUnit){
        int oldMapUnit = GameObj.getUnitId(); //上一状态的位置
        switch (this.getCurrentMapStatus()){
            case INTO_MAP:
                getMapUnits()[nowMapUnit].addUser(GameObj,getCurAreaID(nowMapUnit));
                this.remove();
                break;
            case REDRESS_MAP:
                if(oldMapUnit!=nowMapUnit){ //存在区域的变化
                    getMapUnits()[oldMapUnit].delUser(GameObj,getOldAreaId(nowMapUnit, oldMapUnit));
                    getMapUnits()[nowMapUnit].addUser(GameObj,getNewAreaId(nowMapUnit, oldMapUnit));
                }
                this.remove();
                break;
            case LEAVE_MAP:
                getMapUnits()[oldMapUnit].delUser(GameObj,getCurAreaID(oldMapUnit));
                this.remove();
                break;
            default:
                break;
        }

    }

}
